-
-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weāll occasionally send you account related emails.
Already on GitHub? Sign in to your account
šļø Decorators feature branch #1252
Conversation
Unit Tests Summaryāāāā1 filesāāāāā70 suitesāāā1h 9m 32s ā±ļø Results for commit fad76cd. ā»ļø This comment has been updated with latest results. |
Unit Test Performance Difference
Additional test case details
Results for commit b8edb52 ā»ļø This comment has been updated with latest results. |
ā¦tsengineering/teal.modules.clinical into 1187_decorate_output@main
Signed-off-by: Marcin <[email protected]>
Part of insightsengineering/teal#1371 WIP <details> <summary> Example with decorator </summary> ```r devtools::load_all("../teal") devtools::load_all(".") library(nestcolor) data <- teal_data() data <- within(data, { ADSL <- tmc_ex_adsl ADLB <- tmc_ex_adlb }) join_keys(data) <- default_cdisc_join_keys[names(data)] ADSL <- data[["ADSL"]] ADLB <- data[["ADLB"]] caption_decorator <- function(default_caption = "I am a good decorator", .var_to_replace = "plot") { teal_transform_module( label = "Caption", ui = function(id) shiny::textInput(shiny::NS(id, "footnote"), "Footnote", value = default_caption), server = make_teal_transform_server( substitute({ .var_to_replace <- .var_to_replace + ggplot2::labs(caption = footnote) }, env = list(.var_to_replace = as.name(.var_to_replace))) ) ) } app <- init( data = data, modules = modules( tm_g_ci( label = "Confidence Interval Plot", x_var = data_extract_spec( dataname = "ADSL", select = select_spec( choices = c("ARMCD", "BMRKR2"), selected = c("ARMCD"), multiple = FALSE, fixed = FALSE ) ), y_var = data_extract_spec( dataname = "ADLB", filter = list( filter_spec( vars = "PARAMCD", choices = levels(ADLB$PARAMCD), selected = levels(ADLB$PARAMCD)[1], multiple = FALSE, label = "Select lab:" ), filter_spec( vars = "AVISIT", choices = levels(ADLB$AVISIT), selected = levels(ADLB$AVISIT)[1], multiple = FALSE, label = "Select visit:" ) ), select = select_spec( label = "Analyzed Value", choices = c("AVAL", "CHG"), selected = "AVAL", multiple = FALSE, fixed = FALSE ) ), color = data_extract_spec( dataname = "ADSL", select = select_spec( label = "Color by variable", choices = c("SEX", "STRATA1", "STRATA2"), selected = c("STRATA1"), multiple = FALSE, fixed = FALSE ) ), decorators = list(caption_decorator(.var_to_replace = "plot")) ) ) ) shinyApp(app$ui, app$server) ``` </details> --------- Co-authored-by: Marcin <[email protected]> Co-authored-by: m7pr <[email protected]>
Part of insightsengineering/teal#1371 This module also returns a plot from `cowplot`, and I am not sure if the example I got works well (I am not that familiar with it). <details> <summary>Draft of an example</summary> ````r devtools::load_all("../teal.reporter") devtools::load_all("../teal") devtools::load_all(".") library(nestcolor) library(dplyr) caption_decorator <- function(annotation = "I am a good decorator", var_to_decorate = "plot") { teal_transform_module( label = "Annotation", ui = function(id) shiny::textInput(shiny::NS(id, "annotation"), "Annotation", value = annotation), server = make_teal_transform_server( substitute({ var_to_decorate <- cowplot::add_sub(var_to_decorate, annotation) }, env = list(var_to_decorate = as.name(var_to_decorate))) ) ) } data <- teal_data() data <- within(data, { ADSL <- tmc_ex_adsl ADRS <- tmc_ex_adrs %>% mutate(AVALC = d_onco_rsp_label(AVALC) %>% with_label("Character Result/Finding")) %>% filter(PARAMCD != "OVRINV" | AVISIT == "FOLLOW UP") }) join_keys(data) <- default_cdisc_join_keys[names(data)] ADSL <- data[["ADSL"]] ADRS <- data[["ADRS"]] arm_ref_comp <- list( ARM = list( ref = "B: Placebo", comp = c("A: Drug X", "C: Combination") ), ARMCD = list( ref = "ARM B", comp = c("ARM A", "ARM C") ) ) app <- init( data = data, modules = modules( tm_g_forest_rsp( label = "Forest Response", dataname = "ADRS", arm_var = choices_selected( variable_choices(ADSL, c("ARM", "ARMCD")), "ARMCD" ), arm_ref_comp = arm_ref_comp, paramcd = choices_selected( value_choices(ADRS, "PARAMCD", "PARAM"), "INVET" ), subgroup_var = choices_selected( variable_choices(ADSL, names(ADSL)), c("BMRKR2", "SEX") ), strata_var = choices_selected( variable_choices(ADSL, c("STRATA1", "STRATA2")), "STRATA2" ), plot_height = c(600L, 200L, 2000L), default_responses = list( BESRSPI = list( rsp = c("Stable Disease (SD)", "Not Evaluable (NE)"), levels = c( "Complete Response (CR)", "Partial Response (PR)", "Stable Disease (SD)", "Progressive Disease (PD)", "Not Evaluable (NE)" ) ), INVET = list( rsp = c("Complete Response (CR)", "Partial Response (PR)"), levels = c( "Complete Response (CR)", "Not Evaluable (NE)", "Partial Response (PR)", "Progressive Disease (PD)", "Stable Disease (SD)" ) ), OVRINV = list( rsp = c("Progressive Disease (PD)", "Stable Disease (SD)"), levels = c("Progressive Disease (PD)", "Stable Disease (SD)", "Not Evaluable (NE)") ) ), decorators = list(caption_decorator()) ) ) ) shinyApp(app$ui, app$server) ``` </details> --------- Co-authored-by: Marcin <[email protected]> Co-authored-by: m7pr <[email protected]>
Part of insightsengineering/teal#1371 <details><summary> Working Example </summary> ```r devtools::load_all("../teal.reporter") devtools::load_all("../teal") devtools::load_all(".") library(nestcolor) library(dplyr) caption_decorator <- function(annotation = "I am a good decorator", var_to_decorate = "plot") { teal_transform_module( label = "Annotation", ui = function(id) shiny::textInput(shiny::NS(id, "annotation"), "Annotation", value = annotation), server = make_teal_transform_server( substitute({ var_to_decorate <- cowplot::add_sub(var_to_decorate, annotation) }, env = list(var_to_decorate = as.name(var_to_decorate))) ) ) } data <- teal_data() data <- within(data, { ADSL <- tmc_ex_adsl ADTTE <- tmc_ex_adtte ADSL$RACE <- droplevels(ADSL$RACE) %>% with_label("Race") }) join_keys(data) <- default_cdisc_join_keys[names(data)] ADSL <- data[["ADSL"]] ADTTE <- data[["ADTTE"]] arm_ref_comp <- list( ARM = list( ref = "B: Placebo", comp = c("A: Drug X", "C: Combination") ), ARMCD = list( ref = "ARM B", comp = c("ARM A", "ARM C") ) ) app <- init( data = data, modules = modules( tm_g_forest_tte( label = "Forest Survival", dataname = "ADTTE", arm_var = choices_selected( variable_choices(ADSL, c("ARM", "ARMCD")), "ARMCD" ), arm_ref_comp = arm_ref_comp, paramcd = choices_selected( value_choices(ADTTE, "PARAMCD", "PARAM"), "OS" ), subgroup_var = choices_selected( variable_choices(ADSL, names(ADSL)), c("BMRKR2", "SEX") ), strata_var = choices_selected( variable_choices(ADSL, c("STRATA1", "STRATA2")), "STRATA2" ), decorators = list(caption_decorator()) ) ) ) shinyApp(app$ui, app$server) ``` </details>
Part of insightsengineering/teal#1371 Alternative to #1259 <details><summary> Working Example </summary> ```r devtools::load_all("../teal.reporter") devtools::load_all("../teal") devtools::load_all(".") insert_rrow_decorator <- function(default_caption = "I am a good new row", .var_to_replace = "table") { teal_transform_module( label = "New row", ui = function(id) shiny::textInput(shiny::NS(id, "new_row"), "New row", value = default_caption), server = make_teal_transform_server( substitute({ .var_to_replace <- rtables::insert_rrow(.var_to_replace, rtables::rrow(new_row)) }, env = list(.var_to_replace = as.name(.var_to_replace))) ) ) } library(dplyr) data <- teal_data() data <- within(data, { ADSL <- tmc_ex_adsl ADQS <- tmc_ex_adqs %>% filter(ABLFL != "Y" & ABLFL2 != "Y") %>% mutate( AVISIT = as.factor(AVISIT), AVISITN = rank(AVISITN) %>% as.factor() %>% as.numeric() %>% as.factor(), AVALBIN = AVAL < 50 # Just as an example to get a binary endpoint. ) %>% droplevels() }) join_keys(data) <- default_cdisc_join_keys[names(data)] app <- init( data = data, modules = modules( tm_a_gee( label = "GEE", dataname = "ADQS", aval_var = choices_selected("AVALBIN", fixed = TRUE), id_var = choices_selected(c("USUBJID", "SUBJID"), "USUBJID"), arm_var = choices_selected(c("ARM", "ARMCD"), "ARM"), visit_var = choices_selected(c("AVISIT", "AVISITN"), "AVISIT"), paramcd = choices_selected( choices = value_choices(data[["ADQS"]], "PARAMCD", "PARAM"), selected = "FKSI-FWB" ), cov_var = choices_selected(c("BASE", "AGE", "SEX", "BASE:AVISIT"), NULL), decorators = list(insert_rrow_decorator("Hello world", "table")) ) ) ) if (interactive()) { shinyApp(app$ui, app$server) } ``` </details>
Part of insightsengineering/teal#1371 <details><summary> Working Example </summary> ```r devtools::load_all("../teal") devtools::load_all(".") library(nestcolor) library(dplyr) data <- teal_data() data <- within(data, { ADSL <- tmc_ex_adsl %>% slice(1:20) %>% df_explicit_na() ADLB <- tmc_ex_adlb %>% filter(USUBJID %in% ADSL$USUBJID) %>% df_explicit_na() %>% filter(AVISIT != "SCREENING") }) join_keys(data) <- default_cdisc_join_keys[names(data)] ADSL <- data[["ADSL"]] ADLB <- data[["ADLB"]] caption_decorator <- function(default_caption = "I am a good decorator", .var_to_replace = "plot") { teal_transform_module( label = "Caption", ui = function(id) shiny::textInput(shiny::NS(id, "footnote"), "Footnote", value = default_caption), server = make_teal_transform_server( substitute({ .var_to_replace <- .var_to_replace + ggplot2::labs(caption = footnote) }, env = list(.var_to_replace = as.name(.var_to_replace))) ) ) } app <- init( data = data, modules = modules( tm_g_ipp( label = "Individual Patient Plot", dataname = "ADLB", arm_var = choices_selected( value_choices(ADLB, "ARMCD"), "ARM A" ), paramcd = choices_selected( value_choices(ADLB, "PARAMCD"), "ALT" ), aval_var = choices_selected( variable_choices(ADLB, c("AVAL", "CHG")), "AVAL" ), avalu_var = choices_selected( variable_choices(ADLB, c("AVALU")), "AVALU", fixed = TRUE ), id_var = choices_selected( variable_choices(ADLB, c("USUBJID")), "USUBJID", fixed = TRUE ), visit_var = choices_selected( variable_choices(ADLB, c("AVISIT")), "AVISIT" ), baseline_var = choices_selected( variable_choices(ADLB, c("BASE")), "BASE", fixed = TRUE ), add_baseline_hline = FALSE, separate_by_obs = FALSE, decorators = list(caption_decorator(.var_to_replace = "plot")) ) ) ) if (interactive()) { shinyApp(app$ui, app$server) } ``` </details>
Part of insightsengineering/teal#1371 <details> <summary>Example using cowplot::add_sub with ggplot2</summary> ```r devtools::load_all("../teal.modules.general") devtools::load_all("../teal.reporter") devtools::load_all("../teal") devtools::load_all(".") library(nestcolor) library(dplyr) data <- teal_data() data <- within(data, { ADAE <- tmc_ex_adae ADSL <- tmc_ex_adsl %>% filter(USUBJID %in% ADAE$USUBJID) ADCM <- tmc_ex_adcm %>% mutate( CMSTDY = case_when( CMCAT == "medcl B" ~ 20, CMCAT == "medcl C" ~ 150, TRUE ~ 1 ) %>% with_label("Study Day of Start of Medication"), CMENDY = case_when( CMCAT == "medcl B" ~ 700, CMCAT == "medcl C" ~ 1000, TRUE ~ 500 ) %>% with_label("Study Day of End of Medication"), CMASTDTM = ASTDTM, CMAENDTM = AENDTM ) }) join_keys(data) <- default_cdisc_join_keys[c("ADSL", "ADAE", "ADCM")] adcm_keys <- c("STUDYID", "USUBJID", "ASTDTM", "CMSEQ", "ATC1", "ATC2", "ATC3", "ATC4") join_keys(data)["ADCM", "ADCM"] <- adcm_keys join_keys(data)["ADAE", "ADCM"] <- c("STUDYID", "USUBJID") caption_decorator <- function(annotation = "I am a good decorator", var_to_decorate = "plot") { teal_transform_module( label = "Annotation", ui = function(id) shiny::textInput(shiny::NS(id, "annotation"), "Annotation", value = annotation), server = make_teal_transform_server( substitute({ var_to_decorate <- cowplot::add_sub(var_to_decorate, annotation) }, env = list(var_to_decorate = as.name(var_to_decorate))) ) ) } app <- init( data = data, modules = modules( tm_g_pp_patient_timeline( label = "Patient Timeline", dataname_adae = "ADAE", dataname_adcm = "ADCM", parentname = "ADSL", patient_col = "USUBJID", plot_height = c(600L, 200L, 2000L), cmdecod = choices_selected( choices = variable_choices(data[["ADCM"]], "CMDECOD"), selected = "CMDECOD", ), aeterm = choices_selected( choices = variable_choices(data[["ADAE"]], "AETERM"), selected = c("AETERM") ), aetime_start = choices_selected( choices = variable_choices(data[["ADAE"]], "ASTDTM"), selected = c("ASTDTM") ), aetime_end = choices_selected( choices = variable_choices(data[["ADAE"]], "AENDTM"), selected = c("AENDTM") ), dstime_start = choices_selected( choices = variable_choices(data[["ADCM"]], "CMASTDTM"), selected = c("CMASTDTM") ), dstime_end = choices_selected( choices = variable_choices(data[["ADCM"]], "CMAENDTM"), selected = c("CMAENDTM") ), aerelday_start = choices_selected( choices = variable_choices(data[["ADAE"]], "ASTDY"), selected = c("ASTDY") ), aerelday_end = choices_selected( choices = variable_choices(data[["ADAE"]], "AENDY"), selected = c("AENDY") ), dsrelday_start = choices_selected( choices = variable_choices(data[["ADCM"]], "ASTDY"), selected = c("ASTDY") ), dsrelday_end = choices_selected( choices = variable_choices(data[["ADCM"]], "AENDY"), selected = c("AENDY") ), decorators = list(caption_decorator()) ) ) ) shinyApp(app$ui, app$server) ``` </details> --------- Co-authored-by: m7pr <[email protected]>
Part of insightsengineering/teal#1371 <details><summary> Working Example </summary> ```r devtools::load_all("../teal.reporter") devtools::load_all("../teal") devtools::load_all(".") library(nestcolor) library(dplyr) data <- teal_data() data <- within(data, { ADCM <- tmc_ex_adcm ADSL <- tmc_ex_adsl %>% filter(USUBJID %in% ADCM$USUBJID) ADCM$CMASTDTM <- ADCM$ASTDTM ADCM$CMAENDTM <- ADCM$AENDTM }) join_keys(data) <- default_cdisc_join_keys[c("ADSL", "ADCM")] adcm_keys <- c("STUDYID", "USUBJID", "ASTDTM", "CMSEQ", "ATC1", "ATC2", "ATC3", "ATC4") join_keys(data)["ADCM", "ADCM"] <- adcm_keys ADSL <- data[["ADSL"]] ADCM <- data[["ADCM"]] caption_decorator <- function(default_caption = "I am a good decorator", .var_to_replace = "plot") { teal_transform_module( label = "Caption", ui = function(id) shiny::textInput(shiny::NS(id, "footnote"), "Footnote", value = default_caption), server = make_teal_transform_server( substitute({ .var_to_replace <- .var_to_replace + ggplot2::labs(caption = footnote) }, env = list(.var_to_replace = as.name(.var_to_replace))) ) ) } head_decorator <- function(default_value = 6, .var_to_replace = "object") { teal_transform_module( label = "Head", ui = function(id) shiny::numericInput(shiny::NS(id, "n"), "N rows", value = default_value), server = make_teal_transform_server( substitute({ .var_to_replace <- utils::head(.var_to_replace, n = n) }, env = list(.var_to_replace = as.name(.var_to_replace))) ) ) } app <- init( data = data, modules = modules( tm_g_pp_therapy( label = "Therapy", dataname = "ADCM", parentname = "ADSL", patient_col = "USUBJID", plot_height = c(600L, 200L, 2000L), atirel = choices_selected( choices = variable_choices(ADCM, "ATIREL"), selected = c("ATIREL") ), cmdecod = choices_selected( choices = variable_choices(ADCM, "CMDECOD"), selected = "CMDECOD" ), cmindc = choices_selected( choices = variable_choices(ADCM, "CMINDC"), selected = "CMINDC" ), cmdose = choices_selected( choices = variable_choices(ADCM, "CMDOSE"), selected = "CMDOSE" ), cmtrt = choices_selected( choices = variable_choices(ADCM, "CMTRT"), selected = "CMTRT" ), cmdosu = choices_selected( choices = variable_choices(ADCM, "CMDOSU"), selected = c("CMDOSU") ), cmroute = choices_selected( choices = variable_choices(ADCM, "CMROUTE"), selected = "CMROUTE" ), cmdosfrq = choices_selected( choices = variable_choices(ADCM, "CMDOSFRQ"), selected = "CMDOSFRQ" ), cmstdy = choices_selected( choices = variable_choices(ADCM, "ASTDY"), selected = "ASTDY" ), cmendy = choices_selected( choices = variable_choices(ADCM, "AENDY"), selected = "AENDY" ), decorators = list(plot = caption_decorator('Marcin', 'plot'), table = head_decorator(2, 'table')) ) ) ) if (interactive()) { shinyApp(app$ui, app$server) } ``` </details>
Part of insightsengineering/teal#1371 <details> <summary>Working example</summary> ```r pkgload::load_all("../teal.modules.clinical", export_all = FALSE) # Example below insert_rrow_decorator <- function(default_caption = "I am a good new row", .var_to_replace = "table") { teal_transform_module( label = "New row", ui = function(id) shiny::textInput(shiny::NS(id, "new_row"), "New row", value = default_caption), server = make_teal_transform_server( substitute({ .var_to_replace <- rtables::insert_rrow(.var_to_replace, rtables::rrow(new_row)) }, env = list(.var_to_replace = as.name(.var_to_replace))) ) ) } data <- teal_data() data <- within(data, { ADSL <- tmc_ex_adsl ADLB <- tmc_ex_adlb }) join_keys(data) <- default_cdisc_join_keys[names(data)] ADSL <- data[["ADSL"]] ADLB <- data[["ADLB"]] app <- init( data = data, modules = modules( tm_t_summary_by( label = "Summary by Row Groups Table", dataname = "ADLB", arm_var = choices_selected( choices = variable_choices(ADSL, c("ARM", "ARMCD")), selected = "ARM" ), add_total = TRUE, by_vars = choices_selected( choices = variable_choices(ADLB, c("PARAM", "AVISIT")), selected = c("AVISIT") ), summarize_vars = choices_selected( choices = variable_choices(ADLB, c("AVAL", "CHG")), selected = c("AVAL") ), useNA = "ifany", paramcd = choices_selected( choices = value_choices(ADLB, "PARAMCD", "PARAM"), selected = "ALT" ), decorators = list(insert_rrow_decorator()) ) ) ) |> shiny::runApp() ``` </details> --------- Co-authored-by: Marcin <[email protected]>
Part of insightsengineering/teal#1371 <details> <summary>Working example</summary> ```r pkgload::load_all("../teal.modules.clinical", export_all = FALSE) # Example below insert_rrow_decorator <- function(default_caption = "I am a good new row", .var_to_replace = "table") { teal_transform_module( label = "New row", ui = function(id) shiny::textInput(shiny::NS(id, "new_row"), "New row", value = default_caption), server = make_teal_transform_server( substitute({ .var_to_replace <- rtables::insert_rrow(.var_to_replace, rtables::rrow(new_row)) }, env = list(.var_to_replace = as.name(.var_to_replace))) ) ) } data <- teal_data() data <- within(data, { ADSL <- tmc_ex_adsl ADEG <- tmc_ex_adeg }) join_keys(data) <- default_cdisc_join_keys[names(data)] ADSL <- data[["ADSL"]] ADEG <- data[["ADEG"]] init( data = data, modules = modules( tm_t_shift_by_arm( label = "Shift by Arm Table", dataname = "ADEG", arm_var = choices_selected( variable_choices(ADSL, subset = c("ARM", "ARMCD")), selected = "ARM" ), paramcd = choices_selected( value_choices(ADEG, "PARAMCD"), selected = "HR" ), visit_var = choices_selected( value_choices(ADEG, "AVISIT"), selected = "POST-BASELINE MINIMUM" ), aval_var = choices_selected( variable_choices(ADEG, subset = "ANRIND"), selected = "ANRIND", fixed = TRUE ), baseline_var = choices_selected( variable_choices(ADEG, subset = "BNRIND"), selected = "BNRIND", fixed = TRUE ), useNA = "ifany", decorators = list(insert_rrow_decorator()) ) ) ) |> shiny::runApp() ``` </details>
Part of insightsengineering/teal#1371 <details> <summary>Working example</summary> ```r pkgload::load_all("../teal.modules.clinical", export_all = FALSE) # Example below insert_rrow_decorator <- function(default_caption = "I am a good new row", .var_to_replace = "table") { teal_transform_module( label = "New row", ui = function(id) shiny::textInput(shiny::NS(id, "new_row"), "New row", value = default_caption), server = make_teal_transform_server( substitute({ .var_to_replace <- rtables::insert_rrow(.var_to_replace, rtables::rrow(new_row)) }, env = list(.var_to_replace = as.name(.var_to_replace))) ) ) } data <- teal_data() data <- within(data, { ADSL <- tmc_ex_adsl ADEG <- tmc_ex_adeg }) join_keys(data) <- default_cdisc_join_keys[names(data)] ADSL <- data[["ADSL"]] ADEG <- data[["ADEG"]] init( data = data, modules = modules( tm_t_shift_by_arm_by_worst( label = "Shift by Arm Table", dataname = "ADEG", arm_var = choices_selected( variable_choices(ADSL, subset = c("ARM", "ARMCD")), selected = "ARM" ), paramcd = choices_selected( value_choices(ADEG, "PARAMCD"), selected = "ECGINTP" ), worst_flag_var = choices_selected( variable_choices(ADEG, c("WORS02FL", "WORS01FL")), selected = "WORS02FL" ), worst_flag = choices_selected( value_choices(ADEG, "WORS02FL"), selected = "Y", fixed = TRUE ), aval_var = choices_selected( variable_choices(ADEG, c("AVALC", "ANRIND")), selected = "AVALC" ), baseline_var = choices_selected( variable_choices(ADEG, c("BASEC", "BNRIND")), selected = "BASEC" ), useNA = "ifany", decorators = list(insert_rrow_decorator()) ) ) ) |> shiny::runApp() ``` </details> --------- Co-authored-by: Marcin <[email protected]>
Part of insightsengineering/teal#1371 <details> <summary>Example with decorator</summary> ```r devtools::load_all("../teal") devtools::load_all("../tern") devtools::load_all(".") insert_rrow_decorator <- function(default_caption = "I am a good new row", .var_to_replace = "table") { teal_transform_module( label = "New row", ui = function(id) shiny::textInput(shiny::NS(id, "new_row"), "New row", value = default_caption), server = make_teal_transform_server( substitute({ .var_to_replace <- rtables::insert_rrow(.var_to_replace, rtables::rrow(new_row)) }, env = list(.var_to_replace = as.name(.var_to_replace))) ) ) } library(dplyr) data <- teal_data() data <- within(data, { ADSL <- tmc_ex_adsl ADEX <- tmc_ex_adex set.seed(1, kind = "Mersenne-Twister") .labels <- col_labels(ADEX, fill = FALSE) ADEX <- ADEX %>% distinct(USUBJID, .keep_all = TRUE) %>% mutate( PARAMCD = "TDURD", PARAM = "Overall duration (days)", AVAL = sample(x = seq(1, 200), size = n(), replace = TRUE), AVALU = "Days" ) %>% bind_rows(ADEX) col_labels(ADEX) <- .labels }) join_keys(data) <- default_cdisc_join_keys[names(data)] app <- init( data = data, modules = modules( tm_t_exposure( label = "Duration of Exposure Table", dataname = "ADEX", paramcd = choices_selected( choices = value_choices(data[["ADEX"]], "PARAMCD", "PARAM"), selected = "TDURD" ), col_by_var = choices_selected( choices = variable_choices(data[["ADEX"]], subset = c("SEX", "ARM")), selected = "SEX" ), row_by_var = choices_selected( choices = variable_choices(data[["ADEX"]], subset = c("RACE", "REGION1", "STRATA1", "SEX")), selected = "RACE" ), parcat = choices_selected( choices = value_choices(data[["ADEX"]], "PARCAT2"), selected = "Drug A" ), add_total = FALSE, decorators = list(insert_rrow_decorator()) ) ), filter = teal_slices(teal_slice("ADSL", "SAFFL", selected = "Y")) ) shinyApp(app$ui, app$server) ``` </details> Note: I placed the decorated right above some options to add additional columns and rows. Perhaps we need to review where to place it. I would group these three options in a single panel --------- Signed-off-by: LluĆs Revilla <[email protected]> Co-authored-by: AndrĆ© VerĆssimo <[email protected]>
Part of insightsengineering/teal#1371 <details> <summary>Working example</summary> ```r pkgload::load_all("../teal.modules.clinical", export_all = FALSE) # Example below rlisting_footer <- function(default_footer = "I am a good footer", .var_to_replace = "table") { teal_transform_module( label = "New row", ui = function(id) shiny::textInput(shiny::NS(id, "footer"), "footer", value = default_footer), server = make_teal_transform_server( substitute({ rlistings::main_footer(.var_to_replace) <- footer }, env = list(.var_to_replace = as.name(.var_to_replace))) ) ) } dt_decorator <- function(.color1 = "#f9f9f9", .color2 = "#f0f0f0", .var_to_replace = "table") { teal_transform_module( label = "Table color", ui = function(id) { selectInput( NS(id, "style"), "Table Style", choices = c("Default", "Color1", "Color2"), selected = "Default" ) }, server = function(id, data) { moduleServer(id, function(input, output, session) { logger::log_info("šµ Table row color called to action!", namespace = "teal.modules.general") reactive({ req(data(), input$style) logger::log_info("changing the Table row color '{input$style}'", namespace = "teal.modules.general") teal.code::eval_code(data(), substitute({ .var_to_replace <- switch( style, "Color1" = DT::formatStyle( .var_to_replace, columns = attr(.var_to_replace$x, "colnames")[-1], target = "row", backgroundColor = .color1 ), "Color2" = DT::formatStyle( .var_to_replace, columns = attr(.var_to_replace$x, "colnames")[-1], target = "row", backgroundColor = .color2 ), .var_to_replace ) }, env = list( style = input$style, .var_to_replace = as.name(.var_to_replace), .color1 = .color1, .color2 = .color2 ))) }) }) } ) } data <- teal_data() data <- within(data, { ADSL <- tmc_ex_adsl ADLB <- tmc_ex_adlb }) join_keys(data) <- default_cdisc_join_keys[names(data)] ADSL <- data[["ADSL"]] ADLB <- data[["ADLB"]] init( data = data, modules = modules( tm_t_pp_laboratory( label = "Vitals", dataname = "ADLB", patient_col = "USUBJID", paramcd = choices_selected( choices = variable_choices(ADLB, "PARAMCD"), selected = "PARAMCD" ), param = choices_selected( choices = variable_choices(ADLB, "PARAM"), selected = "PARAM" ), timepoints = choices_selected( choices = variable_choices(ADLB, "ADY"), selected = "ADY" ), anrind = choices_selected( choices = variable_choices(ADLB, "ANRIND"), selected = "ANRIND" ), aval_var = choices_selected( choices = variable_choices(ADLB, "AVAL"), selected = "AVAL" ), avalu_var = choices_selected( choices = variable_choices(ADLB, "AVALU"), selected = "AVALU" ), decorators = list( table_listing = rlisting_footer() ) ) ) ) |> shiny::runApp() ``` </details>
Part of insightsengineering/teal#1371 <details> <summary>Working example</summary> ```r # Load packages pkgload::load_all("../teal.modules.clinical", export_all = FALSE) # Example below insert_rlisting_footer_decorator <- function(default_caption = "I am a good new footer", .var_to_replace = "table") { teal_transform_module( label = "New row", ui = function(id) shiny::textInput(shiny::NS(id, "new_footer"), "New footer", value = default_caption), server = make_teal_transform_server( substitute({ rlistings::main_footer(.var_to_replace) <- new_footer }, env = list(.var_to_replace = as.name(.var_to_replace))) ) ) } data <- teal_data() data <- within(data, { ADSL <- tmc_ex_adsl }) join_keys(data) <- default_cdisc_join_keys[names(data)] ADSL <- data[["ADSL"]] init( data = data, modules = modules( tm_t_pp_basic_info( label = "Basic Info", dataname = "ADSL", patient_col = "USUBJID", vars = choices_selected(choices = variable_choices(ADSL), selected = c("ARM", "AGE", "SEX", "COUNTRY", "RACE", "EOSSTT")), decorators = list( table = insert_rlisting_footer_decorator(.var_to_replace = "table") ) ) ) ) |> shiny::runApp() ``` </details>
Part of insightsengineering/teal#1371 <details> <summary>Working example</summary> ```r # Load packages pkgload::load_all("../teal.modules.clinical", export_all = FALSE) # Example below rlisting_footer <- function(default_footer = "I am a good footer", .var_to_replace = "table_listing") { teal_transform_module( label = "New row", ui = function(id) shiny::textInput(shiny::NS(id, "footer"), "footer", value = default_footer), server = make_teal_transform_server( substitute({ rlistings::main_footer(.var_to_replace) <- footer }, env = list(.var_to_replace = as.name(.var_to_replace))) ) ) } library(dplyr) data <- teal_data() data <- within(data, { ADCM <- tmc_ex_adcm ADSL <- tmc_ex_adsl %>% filter(USUBJID %in% ADCM$USUBJID) ADCM$CMASTDTM <- ADCM$ASTDTM ADCM$CMAENDTM <- ADCM$AENDTM }) join_keys(data) <- default_cdisc_join_keys[names(data)] adcm_keys <- c("STUDYID", "USUBJID", "ASTDTM", "CMSEQ", "ATC1", "ATC2", "ATC3", "ATC4") join_keys(data)["ADCM", "ADCM"] <- adcm_keys ADSL <- data[["ADSL"]] ADCM <- data[["ADCM"]] init( data = data, modules = modules( tm_t_pp_prior_medication( label = "Prior Medication", dataname = "ADCM", parentname = "ADSL", patient_col = "USUBJID", atirel = choices_selected( choices = variable_choices(ADCM, "ATIREL"), selected = "ATIREL" ), cmdecod = choices_selected( choices = variable_choices(ADCM, "CMDECOD"), selected = "CMDECOD" ), cmindc = choices_selected( choices = variable_choices(ADCM, "CMINDC"), selected = "CMINDC" ), cmstdy = choices_selected( choices = variable_choices(ADCM, "ASTDY"), selected = "ASTDY" ), decorators = list( table = rlisting_footer(.var_to_replace = "table") ) ) ) ) |> shiny::runApp() ``` </details>
Part of insightsengineering/teal#1371 <details> <summary>Example with decorators</summary> ```r load_all("../teal") load_all(".") library(dplyr) data <- teal_data() data <- within(data, { ADSL <- tmc_ex_adsl .lbls_adae <- col_labels(tmc_ex_adae) ADAE <- tmc_ex_adae %>% mutate_if(is.character, as.factor) #' be certain of having factors col_labels(ADAE) <- .lbls_adae }) join_keys(data) <- default_cdisc_join_keys[names(data)] ADSL <- data[["ADSL"]] ADAE <- data[["ADAE"]] insert_rrow_decorator <- function(default_caption = "I am a good new row", .var_to_replace = "table") { teal_transform_module( label = "New row", ui = function(id) shiny::textInput(shiny::NS(id, "new_row"), "New row", value = default_caption), server = make_teal_transform_server( substitute({ .var_to_replace <- rtables::insert_rrow(.var_to_replace, rtables::rrow(new_row)) }, env = list(.var_to_replace = as.name(.var_to_replace))) ) ) } app <- init( data = data, modules = modules( tm_t_events_by_grade( label = "Adverse Events by Grade Table", dataname = "ADAE", arm_var = choices_selected(c("ARM", "ARMCD"), "ARM"), llt = choices_selected( choices = variable_choices(ADAE, c("AETERM", "AEDECOD")), selected = c("AEDECOD") ), hlt = choices_selected( choices = variable_choices(ADAE, c("AEBODSYS", "AESOC")), selected = "AEBODSYS" ), grade = choices_selected( choices = variable_choices(ADAE, c("AETOXGR", "AESEV")), selected = "AETOXGR" ), decorators = list(insert_rrow_decorator()) ) ) ) shinyApp(app$ui, app$server) ``` </details> --------- Signed-off-by: LluĆs Revilla <[email protected]> Co-authored-by: AndrĆ© VerĆssimo <[email protected]> Co-authored-by: Marcin <[email protected]>
Part of insightsengineering/teal#1371 <details> <summary>Working example</summary> ```r # Load packages pkgload::load_all("../teal.modules.clinical", export_all = FALSE) # Example below insert_rrow_decorator <- function(default_caption = "I am a good new row", .var_to_replace = "table") { teal_transform_module( label = "New row", ui = function(id) shiny::textInput(shiny::NS(id, "new_row"), "New row", value = default_caption), server = make_teal_transform_server( substitute({ .var_to_replace <- rtables::insert_rrow(.var_to_replace, rtables::rrow(new_row)) }, env = list(.var_to_replace = as.name(.var_to_replace))) ) ) } add_title_decorator <- function(default_check = TRUE, .var_to_replace = "plot") { teal_transform_module( label = "Theme", ui = function(id) shiny::checkboxInput(NS(id, "flag"), "Add title?", TRUE), server = make_teal_transform_server( substitute({ if (flag) .var_to_replace <- .var_to_replace + ggplot2::ggtitle("Title added by decorator") }, env = list(.var_to_replace = as.name(.var_to_replace)) ) ) ) } library(dplyr) arm_ref_comp <- list( ARMCD = list( ref = "ARM B", comp = c("ARM A", "ARM C") ) ) data <- teal_data() data <- within(data, { ADSL <- tmc_ex_adsl ADQS <- tmc_ex_adqs %>% filter(ABLFL != "Y" & ABLFL2 != "Y") %>% filter(AVISIT %in% c("WEEK 1 DAY 8", "WEEK 2 DAY 15", "WEEK 3 DAY 22")) %>% mutate( AVISIT = as.factor(AVISIT), AVISITN = rank(AVISITN) %>% as.factor() %>% as.numeric() %>% as.factor() #' making consecutive numeric factor ) }) join_keys(data) <- default_cdisc_join_keys[names(data)] init( data = data, modules = modules( tm_a_mmrm( label = "MMRM", dataname = "ADQS", aval_var = choices_selected(c("AVAL", "CHG"), "AVAL"), id_var = choices_selected(c("USUBJID", "SUBJID"), "USUBJID"), arm_var = choices_selected(c("ARM", "ARMCD"), "ARM"), visit_var = choices_selected(c("AVISIT", "AVISITN"), "AVISIT"), arm_ref_comp = arm_ref_comp, paramcd = choices_selected( choices = value_choices(data[["ADQS"]], "PARAMCD", "PARAM"), selected = "FKSI-FWB" ), cov_var = choices_selected(c("BASE", "AGE", "SEX", "BASE:AVISIT"), NULL), decorators = list( lsmeans_table = insert_rrow_decorator("A", .var_to_replace = "lsmeans_table") , lsmeans_plot = add_title_decorator("B", .var_to_replace = "lsmeans_plot") , covariance_table = insert_rrow_decorator("C", .var_to_replace = "covariance_table") , fixed_effects_table = insert_rrow_decorator("D", .var_to_replace = "fixed_effects_table") , diagnostic_table = insert_rrow_decorator(.var_to_replace = "diagnostic_table") , diagnostic_plot = add_title_decorator(.var_to_replace = "diagnostic_plot") ) ) ) ) |> shiny::runApp() ``` </details> --------- Co-authored-by: Marcin <[email protected]>
Hey @averissimo 16 tests are failiing, let me know if you need help fixing those! |
Part of insightsengineering/teal#1371 ### Example app with all modules / decorators <details> <summary>Example app</summary> ```r # Load packages pkgload::load_all("../teal.modules.clinical", export_all = FALSE) # Decorators ------------------------------------------------------------------ insert_rrow_decorator <- function(default_caption = "I am a good new row", .var_to_replace = "table") { teal_transform_module( label = "New rtables row", ui = function(id) shiny::textInput(shiny::NS(id, "new_row"), "New row", value = default_caption), server = make_teal_transform_server( substitute({ .var_to_replace <- rtables::insert_rrow(.var_to_replace, rtables::rrow(new_row)) }, env = list(.var_to_replace = as.name(.var_to_replace))) ) ) } add_title_decorator <- function(default_check = TRUE, .var_to_replace = "plot") { teal_transform_module( label = "Title", ui = function(id) shiny::checkboxInput(NS(id, "flag"), "Add title?", TRUE), server = make_teal_transform_server( substitute({ if (flag) .var_to_replace <- .var_to_replace + ggplot2::ggtitle("Title added by decorator") }, env = list(.var_to_replace = as.name(.var_to_replace)) ) ) ) } caption_decorator <- function(default_caption = "I am a good decorator", .var_to_replace = "plot") { teal_transform_module( label = "Caption", ui = function(id) shiny::textInput(shiny::NS(id, "footnote"), "Footnote", value = default_caption), server = make_teal_transform_server( substitute({ .var_to_replace <- .var_to_replace + ggplot2::labs(caption = footnote) }, env = list(.var_to_replace = as.name(.var_to_replace))) ) ) } change_theme_decorator <- function(default_check = TRUE, .var_to_replace = "plot") { teal_transform_module( label = "Theme", ui = function(id) shiny::checkboxInput(NS(id, "flag"), "Apply dark theme?", TRUE), server = make_teal_transform_server( substitute({ if (flag) .var_to_replace <- .var_to_replace + ggplot2::theme_dark() }, env = list(.var_to_replace = as.name(.var_to_replace)) ) ) ) } add_cowplot_title_decorator <- function(default_check = TRUE, .var_to_replace = "plot") { teal_transform_module( label = "Cowplot title", ui = function(id) shiny::checkboxInput(NS(id, "flag"), "Add title?", TRUE), server = make_teal_transform_server( substitute({ if (flag) .var_to_replace <- .var_to_replace + ggplot2::ggtitle("Title added by decorator") + cowplot::theme_cowplot() }, env = list(.var_to_replace = as.name(.var_to_replace)) ) ) ) } rlisting_footer <- function(default_footer = "I am a good footer", .var_to_replace = "table_listing") { teal_transform_module( label = "New row", ui = function(id) shiny::textInput(shiny::NS(id, "footer"), "footer", value = default_footer), server = make_teal_transform_server( substitute({ rlistings::main_footer(.var_to_replace) <- footer }, env = list(.var_to_replace = as.name(.var_to_replace))) ) ) } # End of decorators ----------------------------------------------------------- library(dplyr) # arm_ref_comp <- list(ARMCD = list(ref = "ARM B", comp = c("ARM A", "ARM C"))) arm_ref_comp <- list( ACTARMCD = list(ref = "ARM B", comp = c("ARM A", "ARM C")), ARM = list(ref = "B: Placebo", comp = c("A: Drug X", "C: Combination")) ) data <- within(teal_data(), { ADSL <- tmc_ex_adsl |> mutate(ITTFL = factor("Y") |> with_label("Intent-To-Treat Population Flag")) |> mutate(DTHFL = case_when(!is.na(DTHDT) ~ "Y", TRUE ~ "") |> with_label("Subject Death Flag")) ADAE <- tmc_ex_adae |> filter(!((AETOXGR == 1) & (AESEV == "MILD") & (ARM == "A: Drug X"))) ADAE$ASTDY <- structure( as.double(ADAE$ASTDY, unit = attr(ADAE$ASTDY, "units", exact = TRUE)), label = attr(ADAE$ASTDY, "label", exact = TRUE) ) .lbls_adae <- col_labels(tmc_ex_adae) ADAE <- tmc_ex_adae %>% mutate_if(is.character, as.factor) #' be certain of having factors col_labels(ADAE) <- .lbls_adae ADTTE <- tmc_ex_adtte ADLB <- tmc_ex_adlb |> mutate(AVISIT == forcats::fct_reorder(AVISIT, AVISITN, min)) |> mutate( ONTRTFL = case_when( AVISIT %in% c("SCREENING", "BASELINE") ~ "", TRUE ~ "Y" ) |> with_label("On Treatment Record Flag") ) ADVS <- tmc_ex_advs ADRS <- tmc_ex_adrs |> mutate( AVALC = d_onco_rsp_label(AVALC) |> with_label("Character Result/Finding") ) |> filter(PARAMCD != "OVRINV" | AVISIT == "FOLLOW UP") |> filter(PARAMCD %in% c("BESRSPI", "INVET")) ADAETTE <- tmc_ex_adaette %>% filter(PARAMCD %in% c("AETTE1", "AETTE2", "AETTE3")) %>% mutate(is_event = CNSR == 0) %>% mutate(n_events = as.integer(is_event)) .add_event_flags <- function(dat) { dat <- dat %>% mutate( TMPFL_SER = AESER == "Y", TMPFL_REL = AEREL == "Y", TMPFL_GR5 = AETOXGR == "5", TMP_SMQ01 = !is.na(SMQ01NAM), TMP_SMQ02 = !is.na(SMQ02NAM), TMP_CQ01 = !is.na(CQ01NAM) ) column_labels <- list( TMPFL_SER = "Serious AE", TMPFL_REL = "Related AE", TMPFL_GR5 = "Grade 5 AE", TMP_SMQ01 = aesi_label(dat[["SMQ01NAM"]], dat[["SMQ01SC"]]), TMP_SMQ02 = aesi_label("Y.9.9.9.9/Z.9.9.9.9 AESI"), TMP_CQ01 = aesi_label(dat[["CQ01NAM"]]) ) col_labels(dat)[names(column_labels)] <- as.character(column_labels) dat } ADEX <- tmc_ex_adex set.seed(1, kind = "Mersenne-Twister") .labels <- col_labels(ADEX, fill = FALSE) ADEX <- ADEX %>% distinct(USUBJID, .keep_all = TRUE) %>% mutate( PARAMCD = "TDURD", PARAM = "Overall duration (days)", AVAL = sample(x = seq(1, 200), size = n(), replace = TRUE), AVALU = "Days" ) %>% bind_rows(ADEX) col_labels(ADEX) <- .labels ADCM <- tmc_ex_adcm ADMH <- tmc_ex_admh ADCM$CMASTDTM <- ADCM$ASTDTM ADCM$CMAENDTM <- ADCM$AENDTM ADEG <- tmc_ex_adeg # smq .names_baskets <- grep("^(SMQ|CQ).*NAM$", names(ADAE), value = TRUE) .names_scopes <- grep("^SMQ.*SC$", names(ADAE), value = TRUE) .cs_baskets <- choices_selected( choices = variable_choices(ADAE, subset = .names_baskets), selected = .names_baskets ) .cs_scopes <- choices_selected( choices = variable_choices(ADAE, subset = .names_scopes), selected = .names_scopes, fixed = TRUE ) # summary ADSL$EOSDY[1] <- NA_integer_ }) join_keys(data) <- default_cdisc_join_keys[names(data)] adcm_keys <- c("STUDYID", "USUBJID", "ASTDTM", "CMSEQ", "ATC1", "ATC2", "ATC3", "ATC4") join_keys(data)["ADCM", "ADCM"] <- adcm_keys # Use in choices selected ----------------------------------------------------- ADSL <- data[["ADSL"]] ADQS <- data[["ADQS"]] ADAE <- data[["ADAE"]] ADTTE <- data[["ADTTE"]] ADLB <- data[["ADLB"]] ADAE <- data[["ADAE"]] ADVS <- data[["ADVS"]] ADRS <- data[["ADRS"]] ADAETTE <- data[["ADAETTE"]] ADEX <- data[["ADEX"]] ADCM <- data[["ADCM"]] ADMH <- data[["ADMH"]] ADEG <- data[["ADEG"]] # Init ------------------------------------------------------------------------ init( data = data, modules = modules( # ------------------------------------------------------------------------- tm_t_summary_by( label = "Summary by Row Groups Table", dataname = "ADLB", arm_var = choices_selected( choices = variable_choices(ADSL, c("ARM", "ARMCD")), selected = "ARM" ), add_total = TRUE, by_vars = choices_selected( choices = variable_choices(ADLB, c("PARAM", "AVISIT")), selected = c("AVISIT") ), summarize_vars = choices_selected( choices = variable_choices(ADLB, c("AVAL", "CHG")), selected = c("AVAL") ), useNA = "ifany", paramcd = choices_selected( choices = value_choices(ADLB, "PARAMCD", "PARAM"), selected = "ALT" ), decorators = list(insert_rrow_decorator()) ), # ------------------------------------------------------------------------- tm_t_smq( label = "Adverse Events by SMQ Table", dataname = "ADAE", arm_var = choices_selected( choices = variable_choices(data[["ADSL"]], subset = c("ARM", "SEX")), selected = "ARM" ), add_total = FALSE, baskets = data[[".cs_baskets"]], scopes = data[[".cs_scopes"]], llt = choices_selected( choices = variable_choices(data[["ADAE"]], subset = c("AEDECOD")), selected = "AEDECOD" ), decorators = list(insert_rrow_decorator()) ), # ------------------------------------------------------------------------- tm_t_shift_by_grade( label = "Grade Laboratory Abnormality Table", dataname = "ADLB", arm_var = choices_selected( choices = variable_choices(ADSL, subset = c("ARM", "ARMCD")), selected = "ARM" ), paramcd = choices_selected( choices = value_choices(ADLB, "PARAMCD", "PARAM"), selected = "ALT" ), worst_flag_var = choices_selected( choices = variable_choices(ADLB, subset = c("WGRLOVFL", "WGRLOFL", "WGRHIVFL", "WGRHIFL")), selected = c("WGRLOVFL") ), worst_flag_indicator = choices_selected( value_choices(ADLB, "WGRLOVFL"), selected = "Y", fixed = TRUE ), anl_toxgrade_var = choices_selected( choices = variable_choices(ADLB, subset = c("ATOXGR")), selected = c("ATOXGR"), fixed = TRUE ), base_toxgrade_var = choices_selected( choices = variable_choices(ADLB, subset = c("BTOXGR")), selected = c("BTOXGR"), fixed = TRUE ), add_total = FALSE, decorators = list(insert_rrow_decorator()) ), # ------------------------------------------------------------------------- tm_t_shift_by_arm( label = "Shift by Arm Table", dataname = "ADEG", arm_var = choices_selected( variable_choices(ADSL, subset = c("ARM", "ARMCD")), selected = "ARM" ), paramcd = choices_selected( value_choices(ADEG, "PARAMCD"), selected = "HR" ), visit_var = choices_selected( value_choices(ADEG, "AVISIT"), selected = "POST-BASELINE MINIMUM" ), aval_var = choices_selected( variable_choices(ADEG, subset = "ANRIND"), selected = "ANRIND", fixed = TRUE ), baseline_var = choices_selected( variable_choices(ADEG, subset = "BNRIND"), selected = "BNRIND", fixed = TRUE ), useNA = "ifany", decorators = list(insert_rrow_decorator()) ), # ------------------------------------------------------------------------- tm_t_shift_by_arm_by_worst( label = "Shift by Arm Table (by worst)", dataname = "ADEG", arm_var = choices_selected( variable_choices(ADSL, subset = c("ARM", "ARMCD")), selected = "ARM" ), paramcd = choices_selected( value_choices(ADEG, "PARAMCD"), selected = "ECGINTP" ), worst_flag_var = choices_selected( variable_choices(ADEG, c("WORS02FL", "WORS01FL")), selected = "WORS02FL" ), worst_flag = choices_selected( value_choices(ADEG, "WORS02FL"), selected = "Y", fixed = TRUE ), aval_var = choices_selected( variable_choices(ADEG, c("AVALC", "ANRIND")), selected = "AVALC" ), baseline_var = choices_selected( variable_choices(ADEG, c("BASEC", "BNRIND")), selected = "BASEC" ), useNA = "ifany", decorators = list(insert_rrow_decorator()) ), # ------------------------------------------------------------------------- tm_t_pp_prior_medication( label = "Prior Medication", dataname = "ADCM", parentname = "ADSL", patient_col = "USUBJID", atirel = choices_selected( choices = variable_choices(ADCM, "ATIREL"), selected = "ATIREL" ), cmdecod = choices_selected( choices = variable_choices(ADCM, "CMDECOD"), selected = "CMDECOD" ), cmindc = choices_selected( choices = variable_choices(ADCM, "CMINDC"), selected = "CMINDC" ), cmstdy = choices_selected( choices = variable_choices(ADCM, "ASTDY"), selected = "ASTDY" ), decorators = list( table = rlisting_footer(.var_to_replace = "table") ) ), # ------------------------------------------------------------------------- tm_t_pp_medical_history( label = "Medical History", dataname = "ADMH", parentname = "ADSL", patient_col = "USUBJID", mhterm = choices_selected( choices = variable_choices(ADMH, c("MHTERM")), selected = "MHTERM" ), mhbodsys = choices_selected( choices = variable_choices(ADMH, "MHBODSYS"), selected = "MHBODSYS" ), mhdistat = choices_selected( choices = variable_choices(ADMH, "MHDISTAT"), selected = "MHDISTAT" ), decorators = list(insert_rrow_decorator()) ), # ------------------------------------------------------------------------- tm_t_pp_laboratory( label = "Vitals", dataname = "ADLB", patient_col = "USUBJID", paramcd = choices_selected( choices = variable_choices(ADLB, "PARAMCD"), selected = "PARAMCD" ), param = choices_selected( choices = variable_choices(ADLB, "PARAM"), selected = "PARAM" ), timepoints = choices_selected( choices = variable_choices(ADLB, "ADY"), selected = "ADY" ), anrind = choices_selected( choices = variable_choices(ADLB, "ANRIND"), selected = "ANRIND" ), aval_var = choices_selected( choices = variable_choices(ADLB, "AVAL"), selected = "AVAL" ), avalu_var = choices_selected( choices = variable_choices(ADLB, "AVALU"), selected = "AVALU" ), decorators = list(table = rlisting_footer(.var_to_replace = "table")) ), # ------------------------------------------------------------------------- tm_t_pp_basic_info( label = "Basic Info", dataname = "ADSL", patient_col = "USUBJID", vars = choices_selected(choices = variable_choices(ADSL), selected = c("ARM", "AGE", "SEX", "COUNTRY", "RACE", "EOSSTT")) , decorators = list( table = rlisting_footer(.var_to_replace = "table") ) ), # ------------------------------------------------------------------------- tm_t_mult_events( label = "Concomitant Medications by Medication Class and Preferred Name", dataname = "ADCM", arm_var = choices_selected(c("ARM", "ARMCD"), "ARM"), seq_var = choices_selected("CMSEQ", selected = "CMSEQ", fixed = TRUE), hlt = choices_selected( choices = variable_choices(ADCM, c("ATC1", "ATC2", "ATC3", "ATC4")), selected = c("ATC1", "ATC2", "ATC3", "ATC4") ), llt = choices_selected(choices = variable_choices(ADCM, c("CMDECOD")), selected = c("CMDECOD")), add_total = TRUE, event_type = "treatment", decorators = list(insert_rrow_decorator()) ), # ------------------------------------------------------------------------- tm_t_logistic( label = "Logistic Regression", dataname = "ADRS", arm_var = choices_selected( choices = variable_choices(ADRS, c("ARM", "ARMCD")), selected = "ARM" ), arm_ref_comp = arm_ref_comp, paramcd = choices_selected( choices = value_choices(ADRS, "PARAMCD", "PARAM"), selected = "BESRSPI" ), cov_var = choices_selected( choices = c("SEX", "AGE", "BMRKR1", "BMRKR2"), selected = "SEX" ), decorators = list(insert_rrow_decorator()) ), # ------------------------------------------------------------------------- tm_t_exposure( label = "Duration of Exposure Table", dataname = "ADEX", paramcd = choices_selected( choices = value_choices(data[["ADEX"]], "PARAMCD", "PARAM"), selected = "TDURD" ), col_by_var = choices_selected( choices = variable_choices(data[["ADEX"]], subset = c("SEX", "ARM")), selected = "SEX" ), row_by_var = choices_selected( choices = variable_choices(data[["ADEX"]], subset = c("RACE", "REGION1", "STRATA1", "SEX")), selected = "RACE" ), parcat = choices_selected( choices = value_choices(data[["ADEX"]], "PARCAT2"), selected = "Drug A" ), add_total = FALSE, decorators = list(insert_rrow_decorator()) ), # ------------------------------------------------------------------------- tm_t_events( label = "Adverse Event Table", dataname = "ADAE", arm_var = choices_selected(c("ARM", "ARMCD"), "ARM"), llt = choices_selected( choices = variable_choices(ADAE, c("AETERM", "AEDECOD")), selected = c("AEDECOD") ), hlt = choices_selected( choices = variable_choices(ADAE, c("AEBODSYS", "AESOC")), selected = "AEBODSYS" ), add_total = TRUE, event_type = "adverse event", decorators = list(insert_rrow_decorator()) ), # ------------------------------------------------------------------------- tm_t_events_patyear( label = "AE Rate Adjusted for Patient-Years At Risk Table", dataname = "ADAETTE", arm_var = choices_selected( choices = variable_choices(ADSL, c("ARM", "ARMCD")), selected = "ARMCD" ), add_total = TRUE, events_var = choices_selected( choices = variable_choices(ADAETTE, "n_events"), selected = "n_events", fixed = TRUE ), paramcd = choices_selected( choices = value_choices(ADAETTE, "PARAMCD", "PARAM"), selected = "AETTE1" ), decorators = list(insert_rrow_decorator()) ), # ------------------------------------------------------------------------- tm_t_events_by_grade( label = "Adverse Events by Grade Table", dataname = "ADAE", arm_var = choices_selected(c("ARM", "ARMCD"), "ARM"), llt = choices_selected( choices = variable_choices(ADAE, c("AETERM", "AEDECOD")), selected = c("AEDECOD") ), hlt = choices_selected( choices = variable_choices(ADAE, c("AEBODSYS", "AESOC")), selected = "AEBODSYS" ), grade = choices_selected( choices = variable_choices(ADAE, c("AETOXGR", "AESEV")), selected = "AETOXGR" ), decorators = list(insert_rrow_decorator()) ), # ------------------------------------------------------------------------- tm_t_coxreg( label = "Cox Reg.", dataname = "ADTTE", arm_var = choices_selected(c("ARM", "ARMCD", "ACTARMCD"), "ARM"), arm_ref_comp = arm_ref_comp, paramcd = choices_selected( value_choices(ADTTE, "PARAMCD", "PARAM"), "OS" ), strata_var = choices_selected( c("COUNTRY", "STRATA1", "STRATA2"), "STRATA1" ), cov_var = choices_selected( c("AGE", "BMRKR1", "BMRKR2", "REGION1"), "AGE" ), multivariate = TRUE, decorators = list(insert_rrow_decorator()) ), # ------------------------------------------------------------------------- tm_t_abnormality( label = "Abnormality Table", dataname = "ADLB", arm_var = choices_selected( choices = variable_choices(ADSL, subset = c("ARM", "ARMCD")), selected = "ARM" ), add_total = FALSE, by_vars = choices_selected( choices = variable_choices(ADLB, subset = c("LBCAT", "PARAM", "AVISIT")), selected = c("LBCAT", "PARAM"), keep_order = TRUE ), baseline_var = choices_selected( variable_choices(ADLB, subset = "BNRIND"), selected = "BNRIND", fixed = TRUE ), grade = choices_selected( choices = variable_choices(ADLB, subset = "ANRIND"), selected = "ANRIND", fixed = TRUE ), abnormal = list(low = "LOW", high = "HIGH"), exclude_base_abn = FALSE, decorators = list(insert_rrow_decorator("I am a good new row")) ), # ------------------------------------------------------------------------- tm_g_pp_vitals( label = "Vitals", dataname = "ADVS", parentname = "ADSL", patient_col = "USUBJID", plot_height = c(600L, 200L, 2000L), paramcd = choices_selected( choices = variable_choices(ADVS, "PARAMCD"), selected = "PARAMCD" ), xaxis = choices_selected( choices = variable_choices(ADVS, "ADY"), selected = "ADY" ), aval_var = choices_selected( choices = variable_choices(ADVS, "AVAL"), selected = "AVAL" ), decorators = list(plot = add_title_decorator("plot")) ), # ------------------------------------------------------------------------- tm_g_pp_adverse_events( label = "Adverse Events", dataname = "ADAE", parentname = "ADSL", patient_col = "USUBJID", plot_height = c(600L, 200L, 2000L), aeterm = choices_selected( choices = variable_choices(ADAE, "AETERM"), selected = "AETERM" ), tox_grade = choices_selected( choices = variable_choices(ADAE, "AETOXGR"), selected = "AETOXGR" ), causality = choices_selected( choices = variable_choices(ADAE, "AEREL"), selected = "AEREL" ), outcome = choices_selected( choices = variable_choices(ADAE, "AEOUT"), selected = "AEOUT" ), action = choices_selected( choices = variable_choices(ADAE, "AEACN"), selected = "AEACN" ), time = choices_selected( choices = variable_choices(ADAE, "ASTDY"), selected = "ASTDY" ), decod = NULL, decorators = list( plot = caption_decorator('I am a good caption', 'plot'), table = rlisting_footer(.var_to_replace = 'table') ) ), # ------------------------------------------------------------------------- tm_g_lineplot( label = "Line Plot", dataname = "ADLB", strata = choices_selected( variable_choices(ADSL, c("ARM", "ARMCD", "ACTARMCD")), "ARM" ), y = choices_selected( variable_choices(ADLB, c("AVAL", "BASE", "CHG", "PCHG")), "AVAL" ), param = choices_selected( value_choices(ADLB, "PARAMCD", "PARAM"), "ALT" ), decorators = list(add_cowplot_title_decorator("plot")) ), # ------------------------------------------------------------------------- tm_g_km( label = "Kaplan-Meier Plot", dataname = "ADTTE", arm_var = choices_selected( variable_choices(ADSL, c("ARM", "ARMCD", "ACTARMCD")), "ARM" ), paramcd = choices_selected( value_choices(ADTTE, "PARAMCD", "PARAM"), "OS" ), arm_ref_comp = arm_ref_comp, strata_var = choices_selected( variable_choices(ADSL, c("SEX", "BMRKR2")), "SEX" ), facet_var = choices_selected( variable_choices(ADSL, c("SEX", "BMRKR2")), NULL ), decorators = list(plot = add_cowplot_title_decorator(TRUE, "plot")) ), # ------------------------------------------------------------------------- tm_g_barchart_simple( label = "ADAE Analysis", x = data_extract_spec( dataname = "ADSL", select = select_spec( choices = variable_choices( ADSL, c( "ARM", "ACTARM", "SEX", "RACE", "ITTFL", "SAFFL", "STRATA2" ) ), selected = "ACTARM", multiple = FALSE ) ), fill = list( data_extract_spec( dataname = "ADSL", select = select_spec( choices = variable_choices( ADSL, c( "ARM", "ACTARM", "SEX", "RACE", "ITTFL", "SAFFL", "STRATA2" ) ), selected = "SEX", multiple = FALSE ) ), data_extract_spec( dataname = "ADAE", select = select_spec( choices = variable_choices(ADAE, c("AETOXGR", "AESEV", "AESER")), selected = NULL, multiple = FALSE ) ) ), x_facet = list( data_extract_spec( dataname = "ADAE", select = select_spec( choices = variable_choices(ADAE, c("AETOXGR", "AESEV", "AESER")), selected = "AETOXGR", multiple = FALSE ) ), data_extract_spec( dataname = "ADSL", select = select_spec( choices = variable_choices( ADSL, c( "ARM", "ACTARM", "SEX", "RACE", "ITTFL", "SAFFL", "STRATA2" ) ), selected = NULL, multiple = FALSE ) ) ), y_facet = list( data_extract_spec( dataname = "ADAE", select = select_spec( choices = variable_choices(ADAE, c("AETOXGR", "AESEV", "AESER")), selected = "AESEV", multiple = FALSE ) ), data_extract_spec( dataname = "ADSL", select = select_spec( choices = variable_choices( ADSL, c( "ARM", "ACTARM", "SEX", "RACE", "ITTFL", "SAFFL", "STRATA2" ) ), selected = NULL, multiple = FALSE ) ) ), decorators = list(plot = caption_decorator('The best', 'plot')) ) ) ) |> shiny::runApp() ``` </details> <details> <summary>Second App</summary> ```r # Load packages pkgload::load_all("../teal.modules.clinical", export_all = FALSE) # Example below insert_rrow_decorator <- function(default_caption = "I am a good new row", .var_to_replace = "table") { teal_transform_module( label = "New row", ui = function(id) shiny::textInput(shiny::NS(id, "new_row"), "New row", value = default_caption), server = make_teal_transform_server( substitute({ .var_to_replace <- rtables::insert_rrow(.var_to_replace, rtables::rrow(new_row)) }, env = list(.var_to_replace = as.name(.var_to_replace))) ) ) } # Preparation of the test case - use `EOSDY` and `DCSREAS` variables to demonstrate missing data. data <- teal_data() data <- within(data, { ADSL <- tmc_ex_adsl |> mutate( DTHFL = case_when( !is.na(DTHDT) ~ "Y", TRUE ~ "" ) %>% with_label("Subject Death Flag") ) ADSL$EOSDY[1] <- NA_integer_ ADAE <- tmc_ex_adae .add_event_flags <- function(dat) { dat <- dat %>% mutate( TMPFL_SER = AESER == "Y", TMPFL_REL = AEREL == "Y", TMPFL_GR5 = AETOXGR == "5", TMP_SMQ01 = !is.na(SMQ01NAM), TMP_SMQ02 = !is.na(SMQ02NAM), TMP_CQ01 = !is.na(CQ01NAM) ) column_labels <- list( TMPFL_SER = "Serious AE", TMPFL_REL = "Related AE", TMPFL_GR5 = "Grade 5 AE", TMP_SMQ01 = aesi_label(dat[["SMQ01NAM"]], dat[["SMQ01SC"]]), TMP_SMQ02 = aesi_label("Y.9.9.9.9/Z.9.9.9.9 AESI"), TMP_CQ01 = aesi_label(dat[["CQ01NAM"]]) ) col_labels(dat)[names(column_labels)] <- as.character(column_labels) dat } #' Generating user-defined event flags. ADAE <- ADAE %>% .add_event_flags() .ae_anl_vars <- names(ADAE)[startsWith(names(ADAE), "TMPFL_")] .aesi_vars <- names(ADAE)[startsWith(names(ADAE), "TMP_")] ADTTE <- tmc_ex_adtte # responder ADRS <- tmc_ex_adrs %>% mutate( AVALC = d_onco_rsp_label(AVALC) %>% with_label("Character Result/Finding") ) %>% filter(PARAMCD != "OVRINV" | AVISIT == "FOLLOW UP") ADQS <- tmc_ex_adqs %>% filter(ABLFL != "Y" & ABLFL2 != "Y") %>% filter(AVISIT %in% c("WEEK 1 DAY 8", "WEEK 2 DAY 15", "WEEK 3 DAY 22")) %>% mutate( AVISIT = as.factor(AVISIT), AVISITN = rank(AVISITN) %>% as.factor() %>% as.numeric() %>% as.factor() #' making consecutive numeric factor ) }) join_keys(data) <- default_cdisc_join_keys[names(data)] ADSL <- data[["ADSL"]] ADRS <- data[["ADRS"]] app <- init( data = data, modules = modules( # ------------------------------------------------------------------------- tm_a_mmrm( label = "MMRM", dataname = "ADQS", aval_var = choices_selected(c("AVAL", "CHG"), "AVAL"), id_var = choices_selected(c("USUBJID", "SUBJID"), "USUBJID"), arm_var = choices_selected(c("ARM", "ARMCD"), "ARM"), visit_var = choices_selected(c("AVISIT", "AVISITN"), "AVISIT"), arm_ref_comp = arm_ref_comp, paramcd = choices_selected( choices = value_choices(data[["ADQS"]], "PARAMCD", "PARAM"), selected = "FKSI-FWB" ), cov_var = choices_selected(c("BASE", "AGE", "SEX", "BASE:AVISIT"), NULL) , decorators = list( lsmeans_table = insert_rrow_decorator("A", .var_to_replace = "lsmeans_table") , lsmeans_plot = add_title_decorator("B", .var_to_replace = "lsmeans_plot") , covariance_table = insert_rrow_decorator("C", .var_to_replace = "covariance_table") , fixed_effects_table = insert_rrow_decorator("D", .var_to_replace = "fixed_effects_table") , diagnostic_table = insert_rrow_decorator(.var_to_replace = "diagnostic_table") , diagnostic_plot = add_title_decorator(.var_to_replace = "diagnostic_plot") ) ), # ------------------------------------------------------------------------- tm_t_binary_outcome( label = "Responders", dataname = "ADRS", paramcd = choices_selected( choices = value_choices(ADRS, "PARAMCD", "PARAM"), selected = "BESRSPI" ), arm_var = choices_selected( choices = variable_choices(ADRS, c("ARM", "ARMCD", "ACTARMCD")), selected = "ARM" ), arm_ref_comp = arm_ref_comp, strata_var = choices_selected( choices = variable_choices(ADRS, c("SEX", "BMRKR2", "RACE")), selected = "RACE" ), default_responses = list( BESRSPI = list( rsp = c("Complete Response (CR)", "Partial Response (PR)"), levels = c( "Complete Response (CR)", "Partial Response (PR)", "Stable Disease (SD)", "Progressive Disease (PD)" ) ), INVET = list( rsp = c("Stable Disease (SD)", "Not Evaluable (NE)"), levels = c( "Complete Response (CR)", "Not Evaluable (NE)", "Partial Response (PR)", "Progressive Disease (PD)", "Stable Disease (SD)" ) ), OVRINV = list( rsp = c("Progressive Disease (PD)", "Stable Disease (SD)"), levels = c("Progressive Disease (PD)", "Stable Disease (SD)", "Not Evaluable (NE)") ) ), decorators = list(insert_rrow_decorator("I am a new row")) ), # ------------------------------------------------------------------------- tm_t_events_summary( label = "Adverse Events Summary", dataname = "ADAE", arm_var = choices_selected( choices = variable_choices("ADSL", c("ARM", "ARMCD")), selected = "ARM" ), flag_var_anl = choices_selected( choices = variable_choices("ADAE", data[[".ae_anl_vars"]]), selected = data[[".ae_anl_vars"]][1], keep_order = TRUE, fixed = FALSE ), flag_var_aesi = choices_selected( choices = variable_choices("ADAE", data[[".aesi_vars"]]), selected = data[[".aesi_vars"]][1], keep_order = TRUE, fixed = FALSE ), add_total = TRUE, decorators = list(insert_rrow_decorator()) ), # ------------------------------------------------------------------------- tm_t_summary( label = "Demographic Table", dataname = "ADSL", arm_var = choices_selected(c("ARM", "ARMCD"), "ARM"), add_total = TRUE, summarize_vars = choices_selected( c("SEX", "RACE", "BMRKR2", "EOSDY", "DCSREAS", "AGE"), c("SEX", "RACE") ), useNA = "ifany", decorators = list(insert_rrow_decorator()) ) ) ) |> shiny::runApp() ``` </details>
# Pull Request <!--- Replace `#nnn` with your issue link for reference. --> Part of insightsengineering/teal#1371 (comment) ### Changes description - Tracks changes in the template code of the decorators feature branch - Renames variables to be `plot`, `table` or (in case of multiple decoratable elements) `<name>_plot` and `<name>_table` ### Workflow Manually triggered: https://github.com/insightsengineering/teal.modules.clinical/actions/runs/12359120026 [![Check š ](https://github.com/insightsengineering/teal.modules.clinical/actions/workflows/check.yaml/badge.svg?branch=snapshots%401187_decorate_output%40main)](https://github.com/insightsengineering/teal.modules.clinical/actions/workflows/check.yaml)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
107 files changed! What a journey! Accepting!
Changes description
srv_decorate_data
as utility to append code after decorator (such asprint(plot)
)Checklist for final review:
Double check check for every module:
Todo on feature branch
teal_transform_module
parameter to an extended explanation as suggested heretestthat::test()
Ā #1304Example apps
Not all modules could be used in same App as the examples' data are not 100% compatible. Hence the 2 apps below.
Example app
Second App